from django.shortcuts import render, get_object_or_404, redirect
from django.http import HttpRequest, HttpResponse, JsonResponse
from django.contrib.auth.mixins import LoginRequiredMixin, PermissionRequiredMixin
from .models import BookInstance, Author, Book, BookRating, BookReview, BookFavorite
from django.views import generic
from django.contrib.auth.decorators import permission_required, login_required
from django import forms
from django.urls import reverse_lazy
from django.views.generic.edit import CreateView, UpdateView, DeleteView
from django.db.models import Q, Count, Avg
from django.contrib import messages
from .forms import AuthorForm, BookForm, BookRatingForm, BookReviewForm
from django.views.decorators.http import require_POST
from django.utils.html import escape
import requests
from django.views.decorators.csrf import csrf_exempt

def index(request: HttpRequest) -> HttpResponse:
    num_visits = request.session.get('num_visits', 0)
    request.session['num_visits'] = num_visits + 1
    # 统计
    num_books = Book.objects.count()
    num_authors = Author.objects.count()
    num_available = BookInstance.objects.filter(status='a').count()
    # 借阅排行榜（按借出次数排序，取前5）
    hot_books = Book.objects.annotate(borrowed_count=Count('bookinstance', filter=Q(bookinstance__status='o'))).order_by('-borrowed_count')[:5]
    # 推荐算法（综合用户收藏、点赞、评分、借阅等行为，统计标签/分类，按权重推荐书籍，并生成推荐理由）
    recommend_books = []
    recommend_reason = ''
    if request.user.is_authenticated:
        user = request.user
        tag_weight = {}
        # 收藏（权重5）
        for b in Book.objects.filter(bookfavorite__user=user):
            for t in (b.tags or '').split(','):
                t = t.strip()
                if t:
                    tag_weight[t] = tag_weight.get(t, 0) + 5
        # 点赞（权重4）
        for b in Book.objects.filter(like_count__gt=0):
            for t in (b.tags or '').split(','):
                t = t.strip()
                if t:
                    tag_weight[t] = tag_weight.get(t, 0) + 4
        # 评分（权重3）
        for b in Book.objects.filter(bookrating__user=user):
            for t in (b.tags or '').split(','):
                t = t.strip()
                if t:
                    tag_weight[t] = tag_weight.get(t, 0) + 3
        # 借阅（权重2）
        for inst in BookInstance.objects.filter(borrower=user):
            b = inst.book
            for t in (b.tags or '').split(','):
                t = t.strip()
                if t:
                    tag_weight[t] = tag_weight.get(t, 0) + 2
        # 浏览（权重1，假设有实现）
        # ...
        sorted_tags = sorted(tag_weight.items(), key=lambda x: -x[1])
        tag_list = [t for t, w in sorted_tags if t]
        if tag_list:
            recommend_reason = '因你喜欢 ' + '、'.join(tag_list[:3])
            q = Q()
            for t in tag_list:
                q |= Q(tags__icontains=t)
            recommend_books = Book.objects.filter(q).exclude(bookfavorite__user=user).distinct().order_by('-rating', '-like_count')[:5]
    context = {
        'num_visits': num_visits + 1,
        'num_books': num_books,
        'num_authors': num_authors,
        'num_available': num_available,
        'hot_books': hot_books,
        'famous_authors': Author.objects.annotate(book_count=Count('book')).order_by('-book_count')[:2],
        'recommend_books': recommend_books,
        'recommend_reason': recommend_reason,
    }
    return render(request, 'index.html', context)

class LoanedBooksByUserListView(LoginRequiredMixin, generic.ListView):
    model = BookInstance
    template_name = 'my_borrowed_books.html'
    paginate_by = 10

    def get_queryset(self):
        return BookInstance.objects.filter(borrower=self.request.user, status='o').order_by('due_back')

class RenewBookForm(forms.Form):
    renewal_date = forms.DateField(
        help_text="请输入一个介于今天和4周内的日期。",
        widget=forms.TextInput(attrs={'type': 'date'})
    )

@permission_required('catalog.can_mark_returned', raise_exception=True)
def renew_book_librarian(request, pk):
    book_instance = get_object_or_404(BookInstance, pk=pk)
    if request.method == 'POST':
        form = RenewBookForm(request.POST)
        if form.is_valid():
            book_instance.due_back = form.cleaned_data['renewal_date']
            book_instance.save()
            return redirect('my-borrowed')
    else:
        proposed_renewal_date = book_instance.due_back
        form = RenewBookForm(initial={'renewal_date': proposed_renewal_date})
    return render(request, 'book_renew_librarian.html', {'form': form, 'book_instance': book_instance})

class AuthorCreateView(generic.CreateView):
    model = Author
    form_class = AuthorForm
    template_name = 'author_form.html'
    success_url = reverse_lazy('authors')

class AuthorUpdateView(generic.UpdateView):
    model = Author
    form_class = AuthorForm
    template_name = 'author_form.html'
    success_url = reverse_lazy('authors')

class AuthorDeleteView(generic.DeleteView):
    model = Author
    template_name = 'author_confirm_delete.html'
    success_url = reverse_lazy('authors')

class AuthorListView(generic.ListView):
    model = Author
    template_name = 'author_list.html'
    paginate_by = 10

class AuthorDetailView(generic.DetailView):
    model = Author
    template_name = 'author_detail.html'

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['books'] = Book.objects.filter(author=self.object)
        return context

class AllBorrowedBooksListView(PermissionRequiredMixin, generic.ListView):
    model = BookInstance
    permission_required = 'catalog.can_mark_returned'
    template_name = 'all_borrowed_books.html'
    paginate_by = 10

    def get_queryset(self):
        return BookInstance.objects.filter(status='o').order_by('due_back')

def book_search(request):
    query = request.GET.get('q', '').strip()
    results = []
    if query:
        results = Book.objects.filter(
            Q(title__icontains=query) | Q(author__first_name__icontains=query) | Q(author__last_name__icontains=query)
        )
    context = {
        'query': query,
        'results': results,
    }
    return render(request, 'book_search_results.html', context)

def book_detail(request, pk):
    book = get_object_or_404(Book, pk=pk)
    instances = BookInstance.objects.filter(book=book)
    user = request.user
    can_borrow = user.is_authenticated and instances.filter(status='a').exists()
    user_borrowed = user.is_authenticated and instances.filter(borrower=user, status='o').exists()

    # 评分与评论
    rating_form = None
    review_form = None
    user_rating = None
    if user.is_authenticated:
        user_rating = BookRating.objects.filter(user=user, book=book).first()
        if request.method == 'POST':
            if 'rate' in request.POST:
                rating_form = BookRatingForm(request.POST)
                if rating_form.is_valid():
                    score = rating_form.cleaned_data['score']
                    BookRating.objects.update_or_create(user=user, book=book, defaults={'score': score})
                    # 更新书本平均分
                    ratings = BookRating.objects.filter(book=book)
                    avg = ratings.aggregate(Avg('score'))['score__avg'] or 0
                    book.rating = avg
                    book.rating_count = ratings.count()
                    book.save()
                    messages.success(request, '评分成功！')
                    return redirect('book-detail', pk=book.pk)
            elif 'review' in request.POST:
                review_form = BookReviewForm(request.POST)
                if review_form.is_valid():
                    BookReview.objects.create(user=user, book=book, content=review_form.cleaned_data['content'])
                    messages.success(request, '评论已发表！')
                    return redirect('book-detail', pk=book.pk)
        else:
            rating_form = BookRatingForm(initial={'score': user_rating.score if user_rating else None})
            review_form = BookReviewForm()

    reviews = BookReview.objects.filter(book=book, parent=None).select_related('user')
    context = {
        'book': book,
        'instances': instances,
        'can_borrow': can_borrow,
        'user_borrowed': user_borrowed,
        'rating_form': rating_form,
        'review_form': review_form,
        'user_rating': user_rating,
        'reviews': reviews,
    }
    return render(request, 'book_detail.html', context)

class LoanHistoryView(LoginRequiredMixin, generic.ListView):
    model = BookInstance
    template_name = 'my_loan_history.html'
    paginate_by = 10
    def get_queryset(self):
        return BookInstance.objects.filter(borrower=self.request.user).order_by('-due_back')

class BookCreateView(generic.CreateView):
    model = Book
    form_class = BookForm
    template_name = 'book_form.html'
    success_url = reverse_lazy('index')

class BookUpdateView(generic.UpdateView):
    model = Book
    form_class = BookForm
    template_name = 'book_form.html'
    success_url = reverse_lazy('index')

class BookDeleteView(generic.DeleteView):
    model = Book
    template_name = 'book_confirm_delete.html'
    success_url = reverse_lazy('index')

@require_POST
def like_review(request):
    if not request.user.is_authenticated:
        return JsonResponse({'success': False, 'msg': '请先登录'}, status=403)
    review_id = request.POST.get('review_id')
    try:
        review = BookReview.objects.get(id=review_id)
        review.like_count = review.like_count + 1
        review.save()
        return JsonResponse({'success': True, 'like_count': review.like_count})
    except BookReview.DoesNotExist:
        return JsonResponse({'success': False, 'msg': '评论不存在'}, status=404)

@require_POST
def reply_review(request):
    if not request.user.is_authenticated:
        return JsonResponse({'success': False, 'msg': '请先登录'}, status=403)
    review_id = request.POST.get('review_id')
    content = request.POST.get('content', '').strip()
    if not content:
        return JsonResponse({'success': False, 'msg': '回复内容不能为空'}, status=400)
    try:
        parent = BookReview.objects.get(id=review_id)
        reply = BookReview.objects.create(user=request.user, book=parent.book, content=escape(content), parent=parent)
        return JsonResponse({'success': True, 'reply': {
            'id': reply.id,
            'user': reply.user.username,
            'content': reply.content,
            'created_at': reply.created_at.strftime('%Y-%m-%d %H:%M'),
        }})
    except BookReview.DoesNotExist:
        return JsonResponse({'success': False, 'msg': '评论不存在'}, status=404)

@require_POST
def toggle_favorite(request):
    if not request.user.is_authenticated:
        return JsonResponse({'success': False, 'msg': '请先登录'}, status=403)
    book_id = request.POST.get('book_id')
    try:
        book = Book.objects.get(id=book_id)
        fav, created = BookFavorite.objects.get_or_create(user=request.user, book=book)
        if not created:
            fav.delete()
            book.favorite_count = BookFavorite.objects.filter(book=book).count()
            book.save()
            return JsonResponse({'success': True, 'favorited': False, 'favorite_count': book.favorite_count})
        else:
            book.favorite_count = BookFavorite.objects.filter(book=book).count()
            book.save()
            return JsonResponse({'success': True, 'favorited': True, 'favorite_count': book.favorite_count})
    except Book.DoesNotExist:
        return JsonResponse({'success': False, 'msg': '书籍不存在'}, status=404)

@require_POST
def toggle_like(request):
    if not request.user.is_authenticated:
        return JsonResponse({'success': False, 'msg': '请先登录'}, status=403)
    book_id = request.POST.get('book_id')
    try:
        book = Book.objects.get(id=book_id)
        liked_key = f'liked_book_{book_id}'
        if request.session.get(liked_key):
            if book.like_count > 0:
                book.like_count -= 1
            request.session[liked_key] = False
            book.save()
            return JsonResponse({'success': True, 'liked': False, 'like_count': book.like_count})
        else:
            book.like_count += 1
            request.session[liked_key] = True
            book.save()
            return JsonResponse({'success': True, 'liked': True, 'like_count': book.like_count})
    except Book.DoesNotExist:
        return JsonResponse({'success': False, 'msg': '书籍不存在'}, status=404)

@csrf_exempt
def ai_ask_author(request):
    if request.method == 'POST':
        author_name = request.POST.get('author_name')
        question = request.POST.get('question')
        system_prompt = f"你是{author_name}，请用{author_name}的风格回答问题。"
        api_key = "sk-38S2RwOTRmzMN9aMTu5EAmsDnv0rH1bfKx9PvH6AxdBt0k8t"
        url = "https://api.moonshot.cn/v1/chat/completions"
        headers = {
            "Authorization": f"Bearer {api_key}",
            "Content-Type": "application/json"
        }
        data = {
            "model": "moonshot-v1-8k",
            "messages": [
                {"role": "system", "content": system_prompt},
                {"role": "user", "content": question}
            ]
        }
        resp = requests.post(url, headers=headers, json=data, timeout=30)
        answer = resp.json()['choices'][0]['message']['content']
        return JsonResponse({'answer': answer})
    return JsonResponse({'error': 'Invalid request'}, status=400)

@csrf_exempt
def ai_book_summary(request):
    if request.method == 'POST':
        book_title = request.POST.get('book_title')
        api_key = "sk-38S2RwOTRmzMN9aMTu5EAmsDnv0rH1bfKx9PvH6AxdBt0k8t"
        url = "https://api.moonshot.cn/v1/chat/completions"
        headers = {
            "Authorization": f"Bearer {api_key}",
            "Content-Type": "application/json"
        }
        data = {
            "model": "moonshot-v1-8k",
            "messages": [
                {"role": "system", "content": "你是一个专业的图书内容摘要和推荐AI助手。"},
                {"role": "user", "content": f"请用简洁、专业的语言为《{book_title}》生成一个概要和推荐理由。"}
            ]
        }
        resp = requests.post(url, headers=headers, json=data, timeout=30)
        answer = resp.json()['choices'][0]['message']['content']
        return JsonResponse({'summary': answer})
    return JsonResponse({'error': 'Invalid request'}, status=400)
